# from django.db.models import Count
# from django.contrib.auth.decorators import login_required
# from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
# from django.shortcuts import get_object_or_404, redirect, render
# from django.views.generic import UpdateView, ListView
# from django.utils import timezone
# from django.utils.decorators import method_decorator
# from django.urls import reverse
#
# from .forms import NewTopicForm, PostForm
# from .models import Board, Post, Topic
#
#
# class BoardListView(ListView):
#     model = Board
#     context_object_name = 'boards'
#     template_name = 'home.html'
#
#
# class TopicListView(ListView):
#     model = Topic
#     context_object_name = 'topics'
#     template_name = 'topics.html'
#     paginate_by = 20
#
#     def get_context_data(self, **kwargs):
#         kwargs['board'] = self.board
#         return super().get_context_data(**kwargs)
#
#     def get_queryset(self):
#         self.board = get_object_or_404(Board, pk=self.kwargs.get('pk'))
#         queryset = self.board.topics.order_by('-last_updated').annotate(replies=Count('posts') - 1)
#         return queryset
#
#
# class PostListView(ListView):
#     model = Post
#     context_object_name = 'posts'
#     template_name = 'topic_posts.html'
#     paginate_by = 20
#
#     def get_context_data(self, **kwargs):
#         session_key = 'viewed_topic_{}'.format(self.topic.pk)
#         if not self.request.session.get(session_key, False):
#             self.topic.views += 1
#             self.topic.save()
#             self.request.session[session_key] = True
#         kwargs['topic'] = self.topic
#         return super().get_context_data(**kwargs)
#
#     def get_queryset(self):
#         self.topic = get_object_or_404(Topic, board__pk=self.kwargs.get('pk'), pk=self.kwargs.get('topic_pk'))
#         queryset = self.topic.posts.order_by('created_at')
#         return queryset
#
#
# @login_required
# def new_topic(request, pk):
#     board = get_object_or_404(Board, pk=pk)
#     if request.method == 'POST':
#         form = NewTopicForm(request.POST)
#         if form.is_valid():
#             topic = form.save(commit=False)
#             topic.board = board
#             topic.starter = request.user
#             topic.save()
#             Post.objects.create(
#                 message=form.cleaned_data.get('message'),
#                 topic=topic,
#                 created_by=request.user
#             )
#             return redirect('topic_posts', pk=pk, topic_pk=topic.pk)
#     else:
#         form = NewTopicForm()
#     return render(request, 'new_topic.html', {'board': board, 'form': form})
#
#
# @login_required
# def reply_topic(request, pk, topic_pk):
#     topic = get_object_or_404(Topic, board__pk=pk, pk=topic_pk)
#     if request.method == 'POST':
#         form = PostForm(request.POST)
#         if form.is_valid():
#             post = form.save(commit=False)
#             post.topic = topic
#             post.created_by = request.user
#             post.save()
#
#             topic.last_updated = timezone.now()
#             topic.save()
#
#             topic_url = reverse('topic_posts', kwargs={'pk': pk, 'topic_pk': topic_pk})
#             topic_post_url = '{url}?page={page}#{id}'.format(
#                 url=topic_url,
#                 id=post.pk,
#                 page=topic.get_page_count()
#             )
#
#             return redirect(topic_post_url)
#     else:
#         form = PostForm()
#     return render(request, 'reply_topic.html', {'topic': topic, 'form': form})
#
#
# @method_decorator(login_required, name='dispatch')
# class PostUpdateView(UpdateView):
#     model = Post
#     fields = ('message', )
#     template_name = 'edit_post.html'
#     pk_url_kwarg = 'post_pk'
#     context_object_name = 'post'
#
#     def get_queryset(self):
#         queryset = super().get_queryset()
#         return queryset.filter(created_by=self.request.user)
#
#     def form_valid(self, form):
#         post = form.save(commit=False)
#         post.updated_by = self.request.user
#         post.updated_at = timezone.now()
#         post.save()
#         return redirect('topic_posts', pk=post.topic.board.pk, topic_pk=post.topic.pk)

from django.db.models import Count
from django.contrib.auth.decorators import login_required
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.shortcuts import get_object_or_404, redirect, render
from django.views.generic import UpdateView, ListView
from django.utils import timezone
from django.utils.decorators import method_decorator
from django.urls import reverse

from .forms import NewTopicForm, PostForm
from .models import Board, Post, Topic


class BoardListView(ListView):
    """
    自定义的Board列表视图类。

    继承自Django的ListView类，用于显示板块列表。
    """
    model = Board  # 指定要显示的模型类
    context_object_name = 'boards'  # 指定上下文对象名称，用于在模板中访问数据
    template_name = 'home.html'


class TopicListView(ListView):
    model = Topic
    context_object_name = 'topics'
    template_name = 'topics.html'
    paginate_by = 20

    def get_context_data(self, **kwargs):
        kwargs['board'] = self.board
        return super().get_context_data(**kwargs)

    def get_queryset(self):
        self.board = get_object_or_404(Board, pk=self.kwargs.get('pk'))
        queryset = self.board.topics.order_by('-last_updated').annotate(replies=Count('posts') - 1)
        return queryset

# class TopicListView(ListView):
#     """
#     自定义的Topic列表视图类。
#
#     继承自Django的ListView类，用于显示主题列表。
#     """
#     model = Topic
#     context_object_name = 'topics'
#     # template_name = 'boards/topic_posts.html'  # 修改为正确的模板名称
#     template_name = 'topics.html'  # 修改为正确的模板名称
#     paginate_by = 20  # 设置每页显示的主题数量
#
#     def get_context_data(self, **kwargs):
#         """
#         获取上下文数据。
#
#         在kwargs中添加board对象，以便在模板中使用。
#         """
#         kwargs['board'] = self.board
#         return super().get_context_data(**kwargs)
#
#     def get_queryset(self):
#         """
#         获取主题查询集。
#
#         根据板块ID获取主题，并按最后更新时间排序。
#         """
#         self.board = get_object_or_404(Board, pk=self.kwargs.get('pk'))
#         queryset = self.board.topics.order_by('-last_updated').annotate(replies_count=Count('posts') - 1)
#         return queryset

#
# class TopicListView(ListView):
#     """
#     自定义的Topic列表视图类。
#
#     继承自Django的ListView类，用于显示主题列表。
#     """
#     model = Topic
#     context_object_name = 'topics'
#     template_name = 'topics.html'  # 指定使用的模板文件
#     paginate_by = 20  # 设置每页显示的主题数量
#
#     def get_context_data(self, **kwargs):
#         """
#         获取上下文数据。
#
#         在kwargs中添加board对象，以便在模板中使用。
#         """
#         kwargs['board'] = self.board
#         return super().get_context_data(**kwargs)
#
#     def get_queryset(self):
#         """
#         获取主题查询集。
#
#         根据板块ID获取主题，并按最后更新时间排序。
#         """
#         self.board = get_object_or_404(Board, pk=self.kwargs.get('pk'))
#         queryset = self.board.topics.order_by('-last_updated').annotate(replies_count=Count('posts') - 1)
#         return queryset


class PostListView(ListView):
    """
    自定义的Post列表视图类。

    继承自Django的ListView类，用于显示帖子列表。
    """
    model = Post
    context_object_name = 'posts'
    template_name = 'topic_posts.html'  # 指定使用的模板文件
    paginate_by = 20  # 设置每页显示的帖子数量

    def get_context_data(self, **kwargs):
        """
        获取上下文数据。

        在kwargs中添加topic对象，并处理话题浏览数的统计。
        """
        session_key = 'viewed_topic_{}'.format(self.topic.pk)
        if not self.request.session.get(session_key, False):
            self.topic.views += 1
            self.topic.save()
            self.request.session[session_key] = True
        kwargs['topic'] = self.topic
        return super().get_context_data(**kwargs)

    def get_queryset(self):
        """
        获取帖子查询集。

        根据主题ID获取帖子，并按创建时间排序。
        """
        self.topic = get_object_or_404(Topic, board__pk=self.kwargs.get('pk'), pk=self.kwargs.get('topic_pk'))
        queryset = self.topic.posts.order_by('created_at')
        return queryset


@login_required
def new_topic(request, pk):
    """
    创建新话题。

    参数:
    - request: HttpRequest对象
    - pk: 板块ID

    返回:
    - GET请求: 渲染新话题表单页面
    - POST请求: 处理新话题创建逻辑
    """
    board = get_object_or_404(Board, pk=pk)
    if request.method == 'POST':
        form = NewTopicForm(request.POST)
        if form.is_valid():
            topic = form.save(commit=False)
            topic.board = board
            topic.starter = request.user
            topic.save()
            Post.objects.create(
                message=form.cleaned_data.get('message'),
                topic=topic,
                created_by=request.user
            )
            return redirect('topic_posts', pk=pk, topic_pk=topic.pk)
    else:
        form = NewTopicForm()
    return render(request, 'new_topic.html', {'board': board, 'form': form})


@login_required
def reply_topic(request, pk, topic_pk):
    """
    回复话题。

    参数:
    - request: HttpRequest对象
    - pk: 板块ID
    - topic_pk: 话题ID

    返回:
    - GET请求: 渲染回复话题表单页面
    - POST请求: 处理回复创建逻辑
    """
    topic = get_object_or_404(Topic, board__pk=pk, pk=topic_pk)
    if request.method == 'POST':
        form = PostForm(request.POST)
        if form.is_valid():
            post = form.save(commit=False)
            post.topic = topic
            post.created_by = request.user
            post.save()

            topic.last_updated = timezone.now()
            topic.save()

            topic_url = reverse('topic_posts', kwargs={'pk': pk, 'topic_pk': topic_pk})
            topic_post_url = '{url}?page={page}#{id}'.format(
                url=topic_url,
                id=post.pk,
                page=topic.get_page_count()
            )

            return redirect(topic_post_url)
    else:
        form = PostForm()
    return render(request, 'reply_topic.html', {'topic': topic, 'form': form})


@method_decorator(login_required, name='dispatch')
class PostUpdateView(UpdateView):
    """
    自定义的帖子更新视图类。

    继承自Django的UpdateView类，用于更新帖子内容。
    """
    model = Post
    fields = ('message',)
    template_name = 'edit_post.html'
    pk_url_kwarg = 'post_pk'
    context_object_name = 'post'

    def get_queryset(self):
        """
        获取帖子查询集。

        仅返回当前用户创建的帖子。
        """
        queryset = super().get_queryset()
        return queryset.filter(created_by=self.request.user)

    def form_valid(self, form):
        """
        处理有效的表单提交。

        更新帖子内容，并记录更新者和更新时间。
        """
        post = form.save(commit=False)
        post.updated_by = self.request.user
        post.updated_at = timezone.now()
        post.save()
        return redirect('topic_posts', pk=post.topic.board.pk, topic_pk=post.topic.pk)

#
#
# #
# # def home(request):
# #     """
# #     Home页面的视图函数。
# #
# #     Args:
# #         request: HttpRequest对象，包含用户请求的数据。
# #
# #     Returns:
# #         HttpResponse对象，包含响应的数据。
# #     """
# #
# #     # 查询所有Board对象
# #     boards = Board.objects.all()
# #
# #     # # 初始化一个空列表用于存储Board名称
# #     # boards_names = list()
# #     #
# #     # # 遍历查询结果，将每个Board的名称添加到列表中
# #     # for board in boards:
# #     #     boards_names.append(board.name)
# #     #
# #     # # 将所有Board名称用换行符连接成一个字符串
# #     # response_html = f'<br>'.join(boards_names)
# #     #
# #     # # 返回包含Board名称的HttpResponse对象
# #     # return HttpResponse(response_html)
# #
# #     for board in boards:
# #         last_post = board.get_last_post()
# #         if last_post:
# #             print(f"Board: {board.name}, Last Post Topic PK: {last_post.topic.pk}")
# #         else:
# #             print(f"Board: {board.name}, No last post found.")
# #     # 指向模板引擎的视图
# #     return render(request, 'home.html', {'boards': boards})
# #
# #
# # def board_topics(request, pk):
# #     """
# #     根据指定的板块ID获取并渲染该板块的主题页面。
# #
# #     参数:
# #     - request: HttpRequest对象，表示用户的请求。
# #     - pk: int类型，指定的板块ID。
# #
# #     返回:
# #     渲染的'topics.html'页面，包含指定板块的信息。
# #     """
# #     try:
# #         # 通过PK（主键）获取对应的板块对象
# #         board = get_object_or_404(Board, pk=pk)
# #         topics = board.topics.order_by('-last_updated').annotate(replies_count=Count('posts') - 1)
# #
# #     except Board.DoesNotExist:
# #         # 如果没有找到对应的板块，返回404错误页面
# #         raise Http404
# #     # 渲染'topics.html'模板，将获取的板块对象作为上下文传递
# #     return render(request, 'topics.html', {'board': board,'topics':topics})
# #
# # @login_required
# # def new_topic(request, pk):
# #     """
# #     创建新主题的视图函数。
# #
# #     参数:
# #     - request: HttpRequest对象，包含用户请求的元数据。
# #     - pk: 版块的主键，用于查询特定的版块对象。
# #
# #     返回:
# #     - 渲染的'new_topic.html'模板，包含找到的版块对象。
# #     - 如果没有找到对应的版块，则返回404错误页面。
# #     """
# #     try:
# #         # 尝试根据提供的主键查询版块对象，如果不存在则抛出Http404异常
# #         board = get_object_or_404(Board, pk=pk)
# #         # 获取数据库中的第一个用户作为示例，实际应用中应替换为当前登录用户
# #         # user = User.objects.first()  # TODO: get the currently logged in user
# #
# #         # 处理POST请求
# #         if request.method == 'POST':
# #             # 绑定表单数据到NewTopicForm实例
# #             form = NewTopicForm(request.POST)
# #             # 验证表单数据的有效性
# #             if form.is_valid():
# #                 # 保存表单数据但不提交到数据库，以便添加额外信息
# #                 # topic = form.save(commit=False)
# #                 topic = form.save(commit=False)
# #                 # 关联当前版块和用户到主题
# #                 topic.board = board
# #                 topic.starter = request.user
# #                 topic.save()  # 保存主题到数据库
# #
# #                 # 创建并保存帖子对象
# #                 post = Post.objects.create(
# #                     message=form.cleaned_data.get('message'),
# #                     topic=topic,
# #                     created_by=request.user
# #                 )
# #                 # 重定向到新创建的主题页面
# #                 return redirect('board_topics', pk=board.pk)  # TODO: redirect to the created topic page
# #         else:
# #             # 处理非POST请求，创建空表单
# #             form = NewTopicForm()
# #
# #     except Board.DoesNotExist:
# #         # 如果没有找到对应的板块，返回404错误页面
# #         raise Http404
# #     # 渲染模板并传递版块对象给前端
# #     return render(request, 'new_topic.html', {'board': board, 'form': form})
# #
# # def topic_posts(request, pk, topic_pk):
# #     """
# #     根据给定的板块ID(pk)和主题ID(topic_pk)获取特定主题的详细信息，并将其传递给模板进行渲染。
# #
# #     参数:
# #     - request: HttpRequest对象，包含用户请求的信息。
# #     - pk: int，板块的主键值，用于定位特定的板块。
# #     - topic_pk: int，主题的主键值，用于定位特定的主题。
# #
# #     返回:
# #     - HttpResponse对象，包含渲染后的网页内容。
# #     """
# #     # 使用get_object_or_404函数来获取特定主题，如果找不到匹配的主题，则返回404错误页面。
# #     # 这里同时检查主题所属的板块是否匹配，以确保主题属于正确的板块。
# #     topic = get_object_or_404(Topic, board__pk=pk, pk=topic_pk)
# #     topic.views += 1
# #     topic.save()
# #
# #     # 渲染'topic_posts.html'模板，将获取的主题信息作为上下文传递给模板。
# #     # 这样模板可以根据主题信息来显示具体的帖子内容。
# #     return render(request, 'topic_posts.html', {'topic': topic})
# #
# # @login_required
# # def reply_topic(request, pk, topic_pk):
# #     """
# #     回复主题函数。
# #
# #     该函数用于处理用户回复特定主题的逻辑。它首先确保用户已登录，然后根据提供的主键获取主题。
# #     如果请求方法是POST且表单数据有效，则保存回复并重定向到主题帖子页面。
# #     否则，如果请求方法是GET，它将渲染回复主题的表单。
# #
# #     参数:
# #     - request: HttpRequest对象，表示用户的请求。
# #     - pk: int，板块的主键。
# #     - topic_pk: int，主题的主键。
# #
# #     返回:
# #     - 如果是POST请求且表单数据有效，则重定向到主题帖子页面。
# #     - 如果是GET请求，则渲染回复主题的表单页面。
# #     """
# #     # 根据提供的主键获取主题，如果不存在则返回404错误
# #     topic = get_object_or_404(Topic, board__pk=pk, pk=topic_pk)
# #
# #     if request.method == 'POST':
# #         # 创建PostForm实例，用于处理用户提交的数据
# #         form = PostForm(request.POST)
# #         if form.is_valid():
# #             # 保存表单数据，但暂时不提交到数据库
# #             post = form.save(commit=False)
# #             # 设置回复的主题和创建者
# #             post.topic = topic
# #             post.created_by = request.user
# #             # 保存回复到数据库
# #             post.save()
# #             # 重定向到主题帖子页面
# #             return redirect('topic_posts', pk=pk, topic_pk=topic_pk)
# #     else:
# #         # 如果不是POST请求，则创建一个空的PostForm实例
# #         form = PostForm()
# #
# #     # 渲染回复主题的表单页面
# #     return render(request, 'reply_topic.html', {'topic': topic, 'form': form})
#
# # @method_decorator(login_required, name='dispatch')
# # class PostUpdateView(UpdateView):
# #     """
# #     帖子更新视图类，用于处理帖子的编辑和更新。
# #
# #     继承自Django的UpdateView，针对帖子（Post）模型提供更新功能。
# #     """
# #
# #     # 指定该视图操作的模型为Post
# #     model = Post
# #     # 定义只允许更新Post模型的message字段
# #     fields = ('message',)
# #     # 指定使用的模板文件名为'edit_post.html'
# #     templates_name = 'edit_post.html'
# #     # 设置URL参数中的主键值的关键词参数名为'post_pk'
# #     pk_url_kwarg = 'post_pk'
# #     # 设置上下文中对象的名称为'post'
# #     context_object_name = 'post'
# #
# #     def get_queryset(self):
# #         queryset = super().get_queryset()
# #         return queryset.filter(created_by=self.request.user)
# #
# #     def form_valid(self, form):
# #         """
# #         当表单数据有效时调用此方法，用于保存更新后的帖子信息。
# #
# #         参数:
# #         form: 表单对象，包含用户提交的更新数据。
# #
# #         返回:
# #         重定向到'topic_posts' URL，展示更新后的帖子所在话题的帖子列表。
# #         """
# #         # 保存表单数据但不提交到数据库，以便添加额外信息
# #         post = form.save(commit=False)
# #         # 更新帖子的修改者为当前请求的用户
# #         post.updated_by = self.request.user
# #         # 更新帖子的修改时间为当前时间
# #         post.updated_at = timezone.now()
# #         # 保存更新后的帖子信息到数据库
# #         post.save()
# #         # 重定向到帖子所在话题的帖子列表页面
# #         return redirect('topic_posts', pk=post.topic.board.pk, topic_pk=post.topic.pk)
